home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / vm / vmStack.c < prev    next >
C/C++ Source or Header  |  1990-09-12  |  6KB  |  270 lines

  1. /* vmStack.c -
  2.  *
  3.  *         This file contains routines to allocate and free kernel stacks.  It
  4.  *    is managed by its own monitor.
  5.  *
  6.  * Copyright (C) 1985 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /sprite/src/kernel/vm/RCS/vmStack.c,v 9.4 90/09/12 13:36:40 shirriff Exp $ SPRITE (Berkeley)";
  12. #endif not lint
  13.  
  14. #include <sprite.h>
  15. #include <vm.h>
  16. #include <vmInt.h>
  17. #include <list.h>
  18. #include <proc.h>
  19. #include <sched.h>
  20. #include <sync.h>
  21. #include <sys.h>
  22. #include <dbg.h>
  23.  
  24. Address    vmStackBaseAddr;
  25. Address    vmStackEndAddr;
  26.  
  27. /*
  28.  * Monitor declarations.
  29.  */
  30. Sync_Lock    stackLock;
  31. #define    LOCKPTR    &stackLock
  32.  
  33. /*
  34.  * Stack list element.
  35.  */
  36. typedef struct {
  37.     List_Links    links;
  38.     Address    startAddr;
  39. } StackList;
  40.  
  41. /*
  42.  * Array of stack list information.
  43.  */
  44. static    StackList    *stackListElements;
  45.  
  46. /*
  47.  * There are two stack lists: in use stacks and free stacks.
  48.  */
  49. static    List_Links    activeListHdr;
  50. #define    activeList    (&activeListHdr)
  51. static    List_Links    freeListHdr;
  52. #define    freeList    (&freeListHdr)
  53.  
  54. static    int    numStackPages;
  55.  
  56. static StackList *GetFreeStack _ARGS_((void));
  57. static void FreeStack _ARGS_((Address stackBase));
  58.  
  59.  
  60. /*
  61.  * ----------------------------------------------------------------------------
  62.  *
  63.  * VmStackInit --
  64.  *
  65.  *      Allocate and initialize the stack stuff.
  66.  *
  67.  * Results:
  68.  *      None.
  69.  *
  70.  * Side effects:
  71.  *      Stack information is allocated and initialization.
  72.  *
  73.  * ----------------------------------------------------------------------------
  74.  */
  75. void
  76. VmStackInit()
  77. {
  78.     Address    addr;
  79.     int        i;
  80.  
  81.     Sync_LockInitDynamic(&stackLock, "Vm:stackLock");
  82.     stackListElements =
  83.         (StackList *)Vm_BootAlloc(vmMaxProcesses * sizeof(StackList));
  84.     List_Init(activeList);
  85.     List_Init(freeList);
  86.     for (i = 0, addr = vmStackBaseAddr;
  87.      addr < vmStackEndAddr;
  88.      i++, addr += mach_KernStackSize) {
  89.      stackListElements[i].startAddr = (Address) addr;
  90.      List_Insert((List_Links *) &stackListElements[i], 
  91.              LIST_ATREAR(freeList));
  92.     }
  93.     numStackPages = mach_KernStackSize >> vmPageShift;
  94. }
  95.  
  96.  
  97. /*
  98.  * ----------------------------------------------------------------------------
  99.  *
  100.  * Vm_GetKernelStack --
  101.  *
  102.  *      Allocate a stack for a kernel process.
  103.  *
  104.  * Results:
  105.  *      The base of the new stack.
  106.  *
  107.  * Side effects:
  108.  *      The kernels page table is modified to map in the new stack pages.
  109.  *
  110.  * ----------------------------------------------------------------------------
  111.  */
  112. Address
  113. Vm_GetKernelStack(invalidPage)
  114.     int    invalidPage;    /*Which of the stack pages to make invalid. */
  115. {
  116.     register    Vm_PTE        *ptePtr;
  117.     register    StackList    *stackListPtr;
  118.     register    int        i;
  119.     Vm_VirtAddr            virtAddr;
  120.  
  121.     stackListPtr = GetFreeStack();
  122.     if (stackListPtr == (StackList *) NIL) {
  123.     return((Address)NIL);
  124.     }
  125.  
  126.     /*
  127.      * Need to allocate stack pages and initialize the page table entry.
  128.      * We allocate page table entries for all pages except the first which
  129.      * is protected.
  130.      */
  131.     virtAddr.segPtr = vm_SysSegPtr;
  132.     virtAddr.page = ((unsigned int) stackListPtr->startAddr) >> vmPageShift;
  133.     virtAddr.offset = 0;
  134.     virtAddr.flags = 0;
  135.     virtAddr.sharedPtr = (Vm_SegProcList *)NIL;
  136.     for (i = 0, ptePtr = VmGetPTEPtr(vm_SysSegPtr, virtAddr.page);
  137.      i < numStackPages;
  138.      i++, VmIncPTEPtr(ptePtr, 1), virtAddr.page++) {
  139.     if (i != invalidPage) {
  140.         *ptePtr |= VmPageAllocate(&virtAddr, VM_CAN_BLOCK);
  141.         vmStat.kernStackPages++;
  142.         VmPageValidate(&virtAddr);
  143.     }
  144.     }
  145.     return(stackListPtr->startAddr);
  146. }
  147.  
  148.  
  149. /*
  150.  * ----------------------------------------------------------------------------
  151.  *
  152.  * Vm_FreeKernelStack --
  153.  *
  154.  *      Free up a kernel stack which was allocated at the given address.
  155.  *
  156.  * Results:
  157.  *      None.
  158.  *
  159.  * Side effects:
  160.  *      List of free stacks modified.
  161.  *
  162.  * ----------------------------------------------------------------------------
  163.  */
  164. void
  165. Vm_FreeKernelStack(stackBase)
  166.     Address    stackBase;    /* Virtual address of the stack that is being
  167.                  * freed. */
  168. {
  169.     Vm_VirtAddr            virtAddr;
  170.     register    int        i;
  171.     register    Vm_PTE        *ptePtr;
  172.  
  173.     /*
  174.      * Unmap the stack and free its pages.
  175.      */
  176.     virtAddr.segPtr = vm_SysSegPtr;
  177.     virtAddr.page = (unsigned int) (stackBase) >> vmPageShift;
  178.     virtAddr.offset = 0;
  179.     virtAddr.sharedPtr = (Vm_SegProcList *)NIL;
  180.     virtAddr.flags = 0;
  181.     for (i = 0, ptePtr = VmGetPTEPtr(vm_SysSegPtr, virtAddr.page);
  182.      i < numStackPages; 
  183.      i++, VmIncPTEPtr(ptePtr, 1), virtAddr.page++) {
  184.     if (*ptePtr & VM_PHYS_RES_BIT) {
  185.         vmStat.kernStackPages--;
  186.         VmPageFree(Vm_GetPageFrame(*ptePtr));
  187.         VmPageInvalidate(&virtAddr);
  188.     }
  189.     }
  190.     FreeStack(stackBase);
  191. }
  192.  
  193.  
  194. /*
  195.  *----------------------------------------------------------------------
  196.  *
  197.  * GetFreeStack --
  198.  *
  199.  *    Move a stack from the free list to the active list and return
  200.  *    a pointer to it.
  201.  *
  202.  * Results:
  203.  *    Pointer to free stack, NIL if there aren't any.
  204.  *
  205.  * Side effects:
  206.  *    Lists of free and active kernel stacks are modified..
  207.  *
  208.  *----------------------------------------------------------------------
  209.  */
  210.  
  211. ENTRY static StackList *
  212. GetFreeStack()
  213. {
  214.     register    StackList    *stackListPtr;
  215.  
  216.     LOCK_MONITOR;
  217.  
  218.  
  219.     /*
  220.      * Get the first free stack.
  221.      */
  222.     if (List_IsEmpty(freeList)) {
  223.     stackListPtr = (StackList *) NIL;
  224.     } else {
  225.     stackListPtr = (StackList *) List_First(freeList);
  226.     List_Move((List_Links *) stackListPtr, LIST_ATREAR(activeList));
  227.     }
  228.     UNLOCK_MONITOR;
  229.     return(stackListPtr);
  230. }
  231. /*
  232.  *----------------------------------------------------------------------
  233.  *
  234.  * FreeStack --
  235.  *
  236.  *    Move the stack from the active list to the free list.
  237.  *
  238.  * Results:
  239.  *    None.
  240.  *
  241.  * Side effects:
  242.  *    Lists of free and active kernel stacks are modified..
  243.  *
  244.  *----------------------------------------------------------------------
  245.  */
  246.  
  247. ENTRY static void
  248. FreeStack(stackBase)
  249.     Address    stackBase;    /* Virtual address of the stack that is being
  250.                  * freed. */
  251. {
  252.     register    StackList    *stackListPtr;
  253.  
  254.     LOCK_MONITOR;
  255.  
  256.  
  257.     /*
  258.      * Put the stack back onto the free list.
  259.      */ 
  260.     if (List_IsEmpty(activeList)) {
  261.     panic("Vm_FreeKernelStack: active list empty\n");
  262.     }
  263.     stackListPtr = (StackList *) List_First(activeList);
  264.     List_Move((List_Links *) stackListPtr, LIST_ATREAR(freeList));
  265.     stackListPtr->startAddr = stackBase;
  266.  
  267.     UNLOCK_MONITOR;
  268. }
  269.  
  270.